# include "RenderTargerTexture.h"
# include "d3d11.h"
# include "IndexBufferBindAble.h"
# include "VertexBufferBindAble.h"
# include "VertexScalBufferBindAble.h"
# include "VertexShaderBindAble.h"
# include "PixelShaderBindAble.h"
# include "AnisotropicSamplerBindAble.h"
# include "ShaderResourceViewBindAble.h"

RenderTargerTexture::RenderTargerTexture(ID3D11Device* _device, int _width, int _height)
{
	D3D11_TEXTURE2D_DESC tdesc;
	ZeroMemory(&tdesc, sizeof(D3D11_TEXTURE2D_DESC));
	tdesc.Width = _width;
	tdesc.Height = _height;
	tdesc.MipLevels = 1;
	tdesc.ArraySize = 1;
	tdesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	tdesc.SampleDesc.Count = 1;
	tdesc.SampleDesc.Quality = 0;
	tdesc.Usage = D3D11_USAGE_DEFAULT;
	tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	tdesc.CPUAccessFlags = 0;
	tdesc.MiscFlags = 0;
	_device->CreateTexture2D(&tdesc, nullptr, this->m_texture.GetAddressOf());

	tdesc.Usage = D3D11_USAGE_STAGING;
	tdesc.BindFlags = 0;
	tdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
	_device->CreateTexture2D(&tdesc, nullptr, this->m_copy_texture.GetAddressOf());

	D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;

	renderTargetViewDesc.Format = tdesc.Format;
	renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
	renderTargetViewDesc.Texture2D.MipSlice = 0;
	_device->CreateRenderTargetView(this->m_texture.Get(), &renderTargetViewDesc, this->m_render_target_view.GetAddressOf());



	this->m_bind_able = new std::vector<BindAbleInterface*>();

	this->m_bind_able->push_back(new ShaderResourceViewBindAble(_device, this->m_texture.Get()));

	// 顶点缓存
	const Vertex vertices[] = {
		{-1,	1,	0,	0,	0},
		{1,		1,	0,	1,	0},
		{1,		-1,	0,	1,	1},
		{-1,	-1,	0,	0,	1},
	};
	this->insertBindAble(new VertexBufferBindAble(_device, vertices, sizeof(vertices)));

	// 缩放矩阵
	this->insertBindAble(new VertexScalBufferBindAble(_device, { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f }));

	// 顶点索引
	const UINT16 indices[] = {
		0,1,2, 0,2,3
	};
	this->insertBindAble(new IndexBufferBindAble(_device, indices, sizeof(indices)));
	this->m_index_size = sizeof(indices) / sizeof(UINT16);

	// 顶点着色器
	this->insertBindAble(new VertexShaderBindAble(_device));

	// 像素着色器
	this->insertBindAble(new PixelShaderBindAble(_device));

	// 采样器
	this->insertBindAble(new AnisotropicSamplerBindAble(_device));

}

void RenderTargerTexture::renderTo(ID3D11DeviceContext* _context)
{
	D3D11_VIEWPORT viewPort;
	viewPort.TopLeftX = 0;
	viewPort.TopLeftY = 0;
	viewPort.Width = 2560;
	viewPort.Height = 1440;
	viewPort.MinDepth = 0.0f;
	viewPort.MaxDepth = 1.0f;
	_context->RSSetViewports(1, &viewPort);
	_context->OMSetRenderTargets(1, this->m_render_target_view.GetAddressOf(), nullptr);
	const float bg_color[] = { 0.0f, 0.0f, 0.0f, 0.0f };
	_context->ClearRenderTargetView(this->m_render_target_view.Get(), bg_color);
}

void RenderTargerTexture::bind(ID3D11DeviceContext* _context)
{
	for (auto item : *this->m_bind_able) {
		item->bind(_context);
	}
	_context->DrawIndexed(this->m_index_size, 0u, 0u);
}

void RenderTargerTexture::insertBindAble(BindAbleInterface* _bind_able)
{
	this->m_bind_able->push_back(_bind_able);
}

ID3D11Texture2D* RenderTargerTexture::getCopyTexture() const
{
	return this->m_copy_texture.Get();
}

void RenderTargerTexture::copyTexture(ID3D11DeviceContext* _context)
{
	_context->CopyResource(this->m_copy_texture.Get(), this->m_texture.Get());
	_context->Flush();
}

RenderTargerTexture::~RenderTargerTexture()
{
	for (auto item : *this->m_bind_able) {
		delete item;
	}
}
